package com.zzzs.single;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;

/**
 * 懒汉式单例
 * @author zhu_shuai
 * @since 2021/6/28
 */
public class LazyMan {
    private LazyMan() {
        // System.out.println(Thread.currentThread().getName() + " OK");
        synchronized (LazyMan.class) {
            if (lazyMan != null) {
                throw new RuntimeException("不要试图使用反射破坏异常！");
            }
        }

    }

    private static volatile LazyMan lazyMan; // 加volatile关键字，保证可见性,防止其他线程获取到未初始化完成的对象

    // 双重检测锁模式的 懒汉式单例  DCL懒汉式
    public static LazyMan getInstance() {
        if (lazyMan == null)
        {
            synchronized (LazyMan.class) {
                if (lazyMan == null) {
                    lazyMan = new LazyMan();  // 不是一个原子性操作
                    // System.out.println(lazyMan.hashCode());
                    /**
                     * 指令重排问题
                     * 1. 分配内存空间
                     * 2. 执行构造方法，初始化对象
                     * 3. 把对象指向空间
                     */
                }
            }
        }
        return lazyMan;
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, InterruptedException, BrokenBarrierException {

        // CountDownLatch countDownLatch = new CountDownLatch(1);
        CyclicBarrier cyclicBarrier = new CyclicBarrier(100);
        for (int i = 0; i < 99; i++) {
            new Thread(() -> {
                // System.out.println(Thread.currentThread());
                try {
                    // countDownLatch.await();
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
                System.out.println(new LazyMan().hashCode());
            }).start();
        }
        TimeUnit.SECONDS.sleep(3);
        cyclicBarrier.await();
        System.out.println("end");
        // countDownLatch.await(3, TimeUnit.SECONDS);
        // countDownLatch.countDown();

        // LazyMan instance = LazyMan.getInstance();
        //
        // // 反射获取
        // Class<LazyMan> lazyManClass = LazyMan.class;
        // Constructor<LazyMan> constructor = lazyManClass.getDeclaredConstructor(null);
        // constructor.setAccessible(true);
        // LazyMan instance1 = constructor.newInstance(null);
        // LazyMan instance2 = constructor.newInstance(null);
        //
        // System.out.println(instance1);
        // System.out.println(instance2);
    }
}
